package com.mingke.java.GroupChatPro;

import com.mingke.java.GroupChat.GroupChatUserInfo;

import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Set;

/**
 * @author mingke
 * @function 群聊系统Pro处理连接请求的回调的回调
 * @date 2021/11/10
 */
public class GroupAcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel> {
    //用户名的数组集合
    static String[] userNames = {"张麻子", "武举人","黄四郎","花姐","汤师爷","县长夫人",
            "老三","老二","老五","小六子"};
    //维护一个hashmap用来存储现有的通道
    static HashMap<Integer, AsynchronousSocketChannel> socketChannels = new HashMap<>();

    @Override
    public void completed(AsynchronousSocketChannel socketChannel, AsynchronousServerSocketChannel serverSocketChannel) {
        //客户端连接请求成功的回调
        //将当前连接到的通道加入map
        socketChannels.put(socketChannel.hashCode(), socketChannel);
        //根据当前通道的哈希得到一个随机的用户名
        String userName = userNames[socketChannel.hashCode() % 10];
        //发送消息到所有其他客户端
        String msg = "系统消息@ 客户端："+userName+"加入群聊";
        boardcast(msg, null);
        try {
            //设置当前客户端通道的参数
            socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
            socketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1024);  //接收缓冲区的大小
            socketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 1024);  //发送缓冲区的大小
            //如果端口是开放的状态，设置读取信息的回调
            if(socketChannel.isOpen()) {
                //设置数据读入的缓冲区
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                byteBuffer.clear();
                //设置读取信息的回调
                socketChannel.read(byteBuffer, byteBuffer, new GroupReadHandler(socketChannel));
            }
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            serverSocketChannel.accept(serverSocketChannel, this);
        }
    }

    @Override
    public void failed(Throwable exc, AsynchronousServerSocketChannel serverSocketChannel) {
        try {
            exc.printStackTrace();
        }finally {
            System.out.println("处理客户端接入请求遇到了一点问题");
            serverSocketChannel.accept(serverSocketChannel, this);
        }
    }

    public static void boardcast(String msg, AsynchronousSocketChannel exclude) {
        Set<Integer> keys = socketChannels.keySet();
        for(Integer key : keys) {
            //构建缓冲区信息
            ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));
            if((exclude == null) || (key != exclude.hashCode())) {
                //将数据发送到其他客户端
                socketChannels.get(key).write(byteBuffer, null, new GroupWriteHandler());
            }
            //释放缓冲区
            byteBuffer.clear();
        }
    }

}
